<?php

use Fox\Core\Request;

/**
 * Fox
 *
 * @author keluo <keluo@focrs.com>
 * @copyright 2017 Focrs, Co.,Ltd
 * @since 2017-9-25
 */
class Fox {
    
    private $_configs = [
        'debug' => false, // 调试模式开关
        'rewrite' => true, // url重写开关
        'app' => '', // 应用基本目录
        'timezone' => 'PRC', // 系统运行时区
        'namespace' => [  // 命名空间映射
            'Vendor' => 'app://Vendor'
        ],
    ];
    
    private static $_instance;
    
    private function __construct() {}
    
    public function __destruct() {}
    
    public function __clone() {}
    
    public function __call($method, $arguments) {}
    
    public static function __callstatic($method, $arguments) {}
    
    /**
     * Fox实例
     * @return Fox
     */
    public static function Instance() {
        if(!(self::$_instance instanceof self)) {
            self::$_instance = new self;
        }
        return self::$_instance;
    }
    
    /**
     * 读取配置信息
     * @example Fox::Instance()->debug;
     * @param string $item 配置项
     * @return null|mixed
     */
    public function __get($item) {
        return isset($this->_configs[$item]) ? $this->_configs[$item] : null;
    }
    
    /**
     * 运行框架
     * @param $config 配置信息或配置文件路径
     * @throws Exception
     */
    public function Run($config) {
        $this->LoadConfig($config);
        $this->BuildEnvironment();
        
        $route = $this->app.'/rav/'.(Request::Instance()->route ? : 'index');
        if(file_exists($route.'/action.php') && is_file($route.'/action.php')) {
            $action = include $route.'/action.php';
            $Rf = new ReflectionFunction($action);
            $values = [];
            foreach($Rf->getParameters() as $Rp) {
                if($Rp->isDefaultValueAvailable()) {
                    $values[] = (false !== self::Request()->Get($Rp->name)) ? self::Request()->Get($Rp->name) : $Rp->getDefaultValue();
                } else {
                    if(false === self::Request()->Get($Rp->name)) {
                        throw new Exception('Parameter "'.$Rp->name.'" is required');
                    }
                    $values[] = self::Request()->Get($Rp->name);
                }
            }
            $Rf->InvokeArgs($values);
        } elseif(file_exists($route.'/view.php') && is_file($route.'/view.php')) {
            include $route.'/view.php';
        } else {
            throw new \Exception('404');
        }
    }
    
    /**
     * url管理组件
     * @return \Fox\Core\Url
     */
    public static function Url() {
        static $Instance = null;
        if(is_null($Instance)) $Instance = new \Fox\Core\Url;
        return $Instance;
    }
    
    /**
     * 请求管理组件
     * @return \Fox\Core\Request
     */
    public static function Request() {
        static $Instance = null;
        if(is_null($Instance)) $Instance = \Fox\Core\Request::Instance();
        return $Instance;
    }
    
    /**
     * 请求管理组件
     * @return \Fox\Core\View
     */
    public static function View() {
        static $Instance = null;
        if(is_null($Instance)) $Instance = new \Fox\Core\View;
        return $Instance;
    }
    
    /**
     * 加载配置信息
     * @param string|array $configs 配置文件所在路径|配置信息
     */
    private function LoadConfig($configs) {
        !is_array($configs) && file_exists($configs) && is_file($configs) && $configs = include($configs);
        $this->_configs = array_merge($this->_configs, $configs);
        foreach($this->_configs['namespace'] as $namespace=>$path) {
            if(!is_array($path)) $path = [$path];
            array_walk($path, function(&$v) {
                $v = preg_replace(['/^app\:\/\//', '/^fox\:\/\//'], [Fox::Instance()->app.'/', dirname(__FILE__).'/'], $v);
            });
            $this->_configs['namespace'][$namespace] = $path;
        }
        $this->_configs['namespace']['Fox'] = dirname(__FILE__);
    }
    
    /**
     * 构建框架运行环境
     */
    private function BuildEnvironment() {
        version_compare(PHP_VERSION, '5.4.0', 'lt') && die('Fox requires PHP version 5.4 or higher. (The running is '.PHP_VERSION.')');
        
        date_default_timezone_set($this->timezone); // 设置系统运行环境时区
        
        // 加载自动加载类
        require dirname(__FILE__).'/Core/Autoloader.php';
        // 注册类自动加载机制
        spl_autoload_register(['\\Fox\\Core\\Autoloader', 'LoadClass']);
        
        //系统错误异常被透明捕获进行友好处理
        ini_set('display_errors', 'Off');
        set_error_handler('\\Fox\\Core\\Error::ErrorHandler', E_ALL);
        set_exception_handler('\\Fox\\Core\\Error::ExceptionHandler');
        register_shutdown_function('\\Fox\\Core\\Error::FatalHandler');
    }
    
}